package com.flca.dbs.appengine;

import java.util.Iterator;

import javax.persistence.EntityManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.flca.frw.IEntity;
import com.flca.frw.dao.DaoException;

public abstract class AppEngineDao {

	protected static Logger logger = LoggerFactory.getLogger(AppEngineDao.class);

	private EntityManager em;

	
	public AppEngineDao(EntityManager em) {
		super();
		this.em = em;
	}

	/**
	 * This save's the given IEntity. If the pk is null the entity will be
	 * inserted, otherwise the existing entity will be updated. The pk of the new
	 * or existing object will be returned. TODO return the object and update the
	 * cartridge XxxDaoImpl
	 * 
	 * @param aSource
	 * @param ctx
	 * @return
	 * @throws DaoException
	 */
	public Object save(IEntity aSource) throws DaoException {

		try {
			if (aSource instanceof IEntity) {
				Object result = em.merge(aSource);
				em.flush();
				return ((IEntity) result).getId();
			} else {
				throw new RuntimeException("DaoJpa.save() input object is not a IEnum but " + aSource.getClass().getName());
			}
		} catch (Exception e) {
			logger.error("error in DaoHelper.save :  of " + aSource.toString());
			throw new DaoException(e);
		}
	}

	/**
	 * Return all entities of the given Entity
	 * 
	 * @param aClass
	 * @param ctx
	 * @return
	 * @throws DaoException
	 */
	public Iterator<?> findAll(Class<?> aClass) throws DaoException {
		try {
			javax.persistence.Query query;
			String queryString;
			java.util.List<?> result;

			queryString = "select x from " + aClass.getName() + " x";
			query = em.createQuery(queryString);

			result = query.getResultList();

			return result.iterator();
		} catch (Exception e) {
			logger.error("error in DaoHelper.findAll() of " + aClass);
			throw new DaoException(e);
		}
	}

	/**
	 * return an Entity given the primary key (pk)
	 * 
	 * @param aClass
	 * @param aId
	 * @param ctx
	 * @return
	 * @throws DaoException
	 */
	public Object retrieveById(Class<?> aClass, Object aId) throws DaoException {
		try {
			// System.out.println("aId " + aId.getClass() + "  " + aId);
			if (aId != null) {
				Long pk = new Long(aId.toString());
				return em.find(aClass, pk);
			} else {
				logger.error("DaoHelper.retrieveById() of  class:" + aClass + " called with null ");
				return null;
			}
		} catch (Exception e) {
			logger.error("Error in DaoHelper.retrieveById() of  class:" + aClass + " aId: " + aId);
			throw new DaoException(e);
		}
	}

	/**
	 * remove an Entity given the primary key pk()
	 * 
	 * @param aClass
	 * @param aPk
	 * @param ctx
	 * @throws DaoException
	 */
	public void removeById(Class<?> aClass, Object aPk) throws DaoException {
		try {
			Object obj = em.find(aClass, aPk);
			em.remove(obj);
		} catch (Exception e) {
			logger.error("error in DaoHelper.removeById() of " + aClass);
			throw new DaoException(e);
		}
	}


}
